package com.cy.pj.sys.service.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.util.Arrays;

/**
 * 通过切面学习Spring AOP中各种通知方法的应用
 */
@Order(1)
@Aspect
@Component  //交给spring去管理
public class SysTimeAspect {
    //切面里定义切入点
    @Pointcut("@annotation(com.cy.pj.common.annotation.RequiredTime)")
    public void doTime() {
    }

    //定义通知方法

    /**
     * @Before描述的方法在目标业务执行之前执行 通常会在@Before方法中做一些目标方法参数数据的过滤或预处理
     * 所有非@Around通知方法中都
     */
    @Before("doTime()")
    public void doBefore(JoinPoint joinPoint) {
        System.out.println("@Before");
        Object[] args = joinPoint.getArgs();
        System.out.println(Arrays.toString(args));

    }

    /**
     * @After描述的方法在目标业务执行之后执行(无论是否目标方法出现异常) 通常会在@After描述的方法中进行一些资源释放操作
     */
    @After("doTime()")
    public void doAfter() {
        System.out.println("@After");
    }

    /**
     * @AfterReturning注解描述的方法,在目标方法正常结束时执行
     */
    @AfterReturning("doTime()")
    public void doAfterRetuning() {
        System.out.println("@AfterReturning");
    }

    /**
     * @AfterThrowing注解描述的方法,在目标方法异常结束时执行
     */
    @AfterThrowing("doTime()")
    public void doAfterThrowing() {
        System.out.println("@AfterThrowing");
    }

    @Around("doTime()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("SysLogAspect.@Around.before");
        try {
            Object result = joinPoint.proceed();
            System.out.println("@Around.AfterReturning");
            return result;
        } catch (Throwable e) {
            e.printStackTrace();
            System.out.println("@Around.AfterThrowing");
            throw e;
        } finally {
            System.out.println("@Around.After");
        }
    }
}


